#ifndef AMCUTILITYALGDATAANALYSIS_H
#define AMCUTILITYALGDATAANALYSIS_H

#include <math.h>
#include <armadillo>
using namespace arma;
using namespace std;
class AMCUtilityAlgDataAnalysis
{
public:
	AMCUtilityAlgDataAnalysis() {};

    //*******************************************************************************
    //* 模块名称：IntegrateDataCalc(double *pdData,int number, double dSampleInterval, double dPreIntegrateValue, double *pdDataOut)
    //* 模块功能：积分
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           dSampleInterval	 (in) 定义的样点时间间隔，一般填实际采样点时间间隔
    //*		      dPreIntegrateValue (in) 初始积分值，需要分段数据间连续积分时，填入上一次积分结果最后一个数据，否则填0
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2020-12-24
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int IntegrateDataCalc(T *pdData,int number, double dSampleInterval, double dPreIntegrateValue, T *pdDataOut);


    //*******************************************************************************
    //* 模块名称：DifferenceDataCalc(double *pdData,int number, double dSampleInterval, double dPreDataValue, double dNextDataValue, double *pdDataOut)
    //* 模块功能：微分
    //* 参数说明：*pdData	    	(in) 待运算的数组.
    //*           number	    	(in) 数组长度.
    //*           dSampleInterval	(in) 定义的样点时间间隔，一般填实际采样间隔
    //*			  dPreDataValue		(in) 微分初始数据，需要分段数据间连续微分时，填入上一分段的最后一个数据，否则填0
    //*			  dNextDataValue	(in) 微分追加数据，需要分段数据间连续微分时，填入下一分段的第一个数据，否则填0
    //*           *pdDataOut    	(in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2020-12-24
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int DifferenceDataCalc(T *pdData,int number, double dSampleInterval, double dPreDataValue, double dNextDataValue, T *pdDataOut);

    //*******************************************************************************
    //* 模块名称：ReciprocalDataCalc(double *pdData,int number, double dHighLimitValue, double dLowLimitValue,, double *pdDataOut)
    //* 模块功能：求倒功能
    //* 参数说明：*pdData	    	(in) 待运算的数组.
    //*           number	    	(in) 数组长度.
    //*           dHighLimitValue	(in) 倒数最大值保护限制，一般根据绘图的正最大量程设置
    //*			  dLowLimitValue	(in) 倒数最小值保护限制，一般根据绘图的负最大量程设置
    //*           *pdDataOut    	(in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2020-12-24
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int ReciprocalDataCalc(T *pdData,int number, double dHighLimitValue, double dLowLimitValue, T *pdDataOut);

    //*******************************************************************************
    //* 模块名称：SqrtDataCalc(double *pdData,int number, double *pdDataOut)
    //* 模块功能：重写求平方根功能
    //* 参数说明：*pdData	    	(in) 待运算的数组.
    //*           number	    	(in) 数组长度.
    //*           *pdDataOut    	(OUT) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2020-12-24
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int SqrtDataCalc(T *pdData,int number, T *pdDataOut);


    //*******************************************************************************
    //* 模块名称：ExpDataCalc(double *pdData,int number, double dHighLimitValue, double *pdDataOut)
    //* 模块功能：重写自然指数功能
    //* 参数说明：*pdData	    	(in) 待运算的数组.
    //*           number	    	(in) 数组长度.
    //*           dHighLimitValue	(in) 指数最大值保护限制，一般根据绘图的正最大量程设置
    //*           *pdDataOut    	(in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2020-12-24
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int ExpDataCalc(T *pdData,int number, double dHighLimitValue, T *pdDataOut);

    //*******************************************************************************
    //* 模块名称：AverageCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求平均值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*            number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int AverageCal(T* pdData, int number, T* pdDataOut);


    //*******************************************************************************
    //* 模块名称：MaxCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求最大值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static  int MaxCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：MinCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求最小值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int MinCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：MeanSquareCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求均方值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int MeanSquareCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：VarCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求方差
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-21
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int VarCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：StdCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求标准差
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int StdCal(T* pdData, int number, T* pdDataOut);


    //*******************************************************************************
    //* 模块名称：StdCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求偏度时的标准差定义
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    //求偏度时的标准差定义
    template<class T>
    static int StdCal2(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：PeakpeakCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求峰峰值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int PeakpeakCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：PeakCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求峰值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int PeakCal(T* pdData, int number, T* pdDataOut, T* n);

    //*******************************************************************************
    //* 模块名称：ValidCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求有效值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int ValidCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：PeakCCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求峰值因子
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int PeakCCal(T* pdData, int number, T* pdDataOut, T* n);

    //*******************************************************************************
    //* 模块名称：PulsefactorCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求脉冲因子
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int PulsefactorCal(T* pdData, int number, T* pdDataOut, T* n);

    //*******************************************************************************
    //* 模块名称：MarginfactorCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求裕度因子
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int MarginfactorCal(T* pdData, int number, T* pdDataOut, T* n);

    //*******************************************************************************
    //* 模块名称：FormfactorCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求波形因子
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int FormfactorCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：SquarerootAmCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求方根幅值
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int SquarerootAmCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：SkewnessCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求偏度
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int SkewnessCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：KurtosisCal(T* pdData,int number, T* pdDataOut)
    //* 模块功能：求峭度
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int KurtosisCal(T* pdData, int number, T* pdDataOut);

    //*******************************************************************************
    //* 模块名称：time_parameter_calculata(T* pdData, int number, vector<vector<double>>& pdDataout)
    //* 模块功能：时域特征参数处理
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*           number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的变量数组.
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：2023-11-22
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
    static int time_parameter_calculata(T* pdData, int number, vector<vector<double>>& pdDataout);

    //*******************************************************************************
    //* 模块名称：FFTCal(T* pdData,int number, int fftlen,T* pdDataOut)
    //* 模块功能：求FFT
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*            number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //*            fftlen            (in) FFT运算长度
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
    template<class T>
	static int FFTCal(T* pdData, double fs, int number,
		int fftlen, vector<vector<double>>* pdDataOut);

    //*******************************************************************************
    //* 模块名称：EnvelopeCal(T* pdData,int number, int fftlen,T* pdDataOut)
    //* 模块功能：包络分析
    //* 参数说明：*pdData	    	 (in) 待运算的数组.
    //*            number	    	 (in) 数组长度.
    //*           *pdDataOut    	 (in) 运算完的数组.
    //*            fftlen            (in) FFT运算长度
    //* 返回值  ：0:计算成功 -1:计算失败
    //* 建立时间：
    //* 创建人员：
    //* 修改日期：
    //* 修改人员：
    //*******************************************************************************
      template<class T>
	  static int EnvelopeCal(T* pdData, double fs, int number,
		  int fftlen, vector<vector<double>>* pdDataOut);

};

template<class T>
int AMCUtilityAlgDataAnalysis::IntegrateDataCalc(T *pdData,int number, double dSampleInterval, double dPreIntegrateValue, T *pdDataOut)
{
    double dTempIntegrateValue = dPreIntegrateValue;
    int i;

    if( (number < 1) || (pdData == 0) || (dSampleInterval <= 0.0) || (pdDataOut == 0) )
     {
         return -1;
     }


     pdDataOut[0] = dTempIntegrateValue;

     for( i = 1; i < number; i++ )
     {
         dTempIntegrateValue = dTempIntegrateValue + (pdData[i] + pdData[i -1]) / 2.0 * dSampleInterval;
         pdDataOut[i] =  dTempIntegrateValue;
     }

     return 0;
}

template<class T>
int AMCUtilityAlgDataAnalysis::DifferenceDataCalc(T *pdData,int number, double dSampleInterval, double dPreDataValue, double dNextDataValue, T *pdDataOut)
{
    int i;
    if( (number < 1) || (pdData == 0) || (dSampleInterval <= 0.0) || (pdDataOut == 0) )
     {
         return -1;
     }


     for( i = 0; i < number; i++ )
     {
         if( i ==0 )
         {
             pdDataOut[i] = (pdData[i + 1] - dPreDataValue) / dSampleInterval / 2.0;
         }
         else if( i < (number - 1) )
         {
             pdDataOut[i] = (pdData[i + 1] - pdData[i - 1]) / dSampleInterval / 2.0;
         }
         else
         {
             pdDataOut[i] = (dNextDataValue - pdData[i - 1]) / dSampleInterval / 2.0;
         }
     }

     return 0;

}

template<class T>
int AMCUtilityAlgDataAnalysis::ReciprocalDataCalc(T *pdData,int number, double dHighLimitValue, double dLowLimitValue, T *pdDataOut)
{
     int i;
     double dTempReciprocalData;

    if( (number < 1) || (pdData == 0) || (pdDataOut == 0) || (dHighLimitValue < dLowLimitValue))
     {
         return -1;
     }

     for( i = 0; i < number; i++ )
     {
        if( pdData[i] == 0.0 )
        {
            dTempReciprocalData = __DBL_MAX__;
        }
        else
        {
            dTempReciprocalData = 1.0 / pdData[i] ;
        }

        if( dTempReciprocalData > dHighLimitValue )
        {
            pdDataOut[i] = dHighLimitValue;
        }
        else if( dTempReciprocalData < dLowLimitValue )
        {
            pdDataOut[i] = dLowLimitValue;
        }
        else
        {
            pdDataOut[i] = 	dTempReciprocalData;
        }
     }

     return 0;
}

template<class T>
int AMCUtilityAlgDataAnalysis::SqrtDataCalc(T *pdData,int number, T *pdDataOut)
{
     int i;
    if( (number < 1) || (pdData == 0) || (pdDataOut == 0) )
     {
         return -1;
     }

     for( i = 0; i < number; i++ )
     {
        pdDataOut[i] =  sqrt( fabs( pdData[i] ) );
     }

     return 0;
}

template<class T>
int AMCUtilityAlgDataAnalysis::ExpDataCalc(T *pdData,int number, double dHighLimitValue, T *pdDataOut)
{
     int i;
     double dTempExpData;

    if( (number < 1) || (pdData == 0) || (pdDataOut == 0) || (dHighLimitValue <= 0.0))
     {
         return -1;
     }

     for( i = 0; i < number; i++ )
     {
        dTempExpData = exp( pdData[i] );
        if( dTempExpData > dHighLimitValue )
        {
            pdDataOut[i] = dHighLimitValue;
        }
        else
        {
            pdDataOut[i] = 	dTempExpData;
        }
     }

     return 0;

}

//*******************************************************************************
//* 模块名称：AverageCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求平均值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*            number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::AverageCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double sum = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        sum = sum + abs(pdData[i]);
    }
    *pdDataOut = sum / number;
    return 0;
}

//*******************************************************************************
//* 模块名称：MaxCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求最大值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::MaxCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double max = pdData[0];
    for (int i = 1; i < number; i++) {
        if (pdData[i] > max) {
            max = pdData[i];
        }
    }
    *pdDataOut = max;
    return 0;
}

//*******************************************************************************
//* 模块名称：MinCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求最小值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::MinCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double min = pdData[0];
    for (int i = 1; i < number; i++) {
        if (pdData[i] < min) {
            min = pdData[i];
        }
    }
    *pdDataOut = min;
    return 0;
}

//*******************************************************************************
//* 模块名称：MeanSquareCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求均方值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::MeanSquareCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double MeanSquare = 0;
    int i;
    double p2;
    for (i = 0; i < number; i++)
    {
        p2 = pdData[i] * pdData[i];
        MeanSquare += p2;
    }
    *pdDataOut = MeanSquare / number;
    return 0;
}

//*******************************************************************************
//* 模块名称：VarCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求方差
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-21
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::VarCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    AverageCal(pdData, number, pdDataOut);
    double VarCal = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        VarCal = VarCal + (pdData[i] - *pdDataOut) * (pdData[i] - *pdDataOut);
    }
    *pdDataOut = VarCal / (number - 1);
    return 0;
}

//*******************************************************************************
//* 模块名称：StdCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求标准差
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::StdCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    AverageCal(pdData, number, pdDataOut);
    double StdCal = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        StdCal = StdCal + (pdData[i] - *pdDataOut) * (pdData[i] - *pdDataOut);
    }
    *pdDataOut = sqrt(StdCal / (number - 1));
    return 0;
}
//求偏度时的标准差定义
template<class T>
int AMCUtilityAlgDataAnalysis::StdCal2(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    AverageCal(pdData, number, pdDataOut);
    double StdCal = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        StdCal = StdCal + (pdData[i] - *pdDataOut) * (pdData[i] - *pdDataOut);
    }
    *pdDataOut = sqrt(StdCal / (number - 0));
    return 0;
}

//*******************************************************************************
//* 模块名称：PeakpeakCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求峰峰值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::PeakpeakCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double pdDataOut1 = 0;
    double pdDataOut2 = 0;
    MaxCal(pdData, number, &pdDataOut1);
    MinCal(pdData, number, &pdDataOut2);
    *pdDataOut = pdDataOut1 - pdDataOut2;
    return 0;
}

//*******************************************************************************
//* 模块名称：PeakCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求峰值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::PeakCal(T* pdData, int number, T* pdDataOut, T* n)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int i;
    int j = 0;
    for (i = 1; i < number - 1; i++) {
        if ((pdData[i] > pdData[i - 1]) && (pdData[i] > pdData[i + 1]))
        {
            pdDataOut[j] = pdData[i];
            j++;
        }
    }
    *n = j;
    return 0;
}

//*******************************************************************************
//* 模块名称：ValidCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求有效值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::ValidCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double Valid = 0;
    int i;
    double p2;
    for (i = 0; i < number; i++)
    {
        p2 = pdData[i] * pdData[i];
        Valid += p2;
    }
    *pdDataOut = sqrt(Valid / number);
    return 0;
}

//*******************************************************************************
//* 模块名称：PeakCCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求峰值因子
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::PeakCCal(T* pdData, int number, T* pdDataOut, T* n)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double* peak = new double[number];
    double lenp = 0;
    PeakCal(pdData, number, peak, &lenp);
    double rms = 0;
    ValidCal(pdData, number, &rms);
    for (int i = 0; i < lenp; i++)
    {
        pdDataOut[i] = peak[i] / rms;
    }
    *n = lenp;
    return 0;
}

//*******************************************************************************
//* 模块名称：PulsefactorCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求脉冲因子
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::PulsefactorCal(T* pdData, int number, T* pdDataOut, T* n)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int i;
    int j = 0;
    double* pdData_abs = new double[number];
    for (i = 0; i < number; i++)
    {
        pdData_abs[i] = abs(pdData[i]);
    }
    double ave2;
    AverageCal(pdData_abs, number, &ave2);
    for (i = 1; i < number - 1; i++) {
        if ((pdData[i] > pdData[i - 1]) && (pdData[i] > pdData[i + 1]))
        {
            j++;
            pdDataOut[j - 1] = pdData[i];
        }
    }
    *n = j;
    int cnum;
    for (cnum = 0; cnum < j; cnum++) {
        pdDataOut[cnum] = pdDataOut[cnum] / ave2;
    }
    return 0;
}

//*******************************************************************************
//* 模块名称：MarginfactorCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求裕度因子
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::MarginfactorCal(T* pdData, int number, T* pdDataOut, T* n)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int i;
    int j = 0;
    double* pdData_abs_sqrt = new double[number];
    for (i = 0; i < number; i++)
    {
        pdData_abs_sqrt[i] = sqrt(abs(pdData[i]));
    }
    double ave3;
    AverageCal(pdData_abs_sqrt, number, &ave3);
    ave3 = ave3 * ave3;
    for (i = 1; i < number - 1; i++) {
        if ((pdData[i] > pdData[i - 1]) && (pdData[i] > pdData[i + 1]))
        {
            j++;
            pdDataOut[j - 1] = pdData[i];
        }
    }
    *n = j;
    int cnum;
    for (cnum = 0; cnum < j; cnum++) {
        pdDataOut[cnum] = pdDataOut[cnum] / ave3;
    }
    return 0;
}

//*******************************************************************************
//* 模块名称：FormfactorCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求波形因子
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::FormfactorCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int i;
    double* pdData_abs_sqrt = new double[number];
    for (i = 0; i < number; i++)
    {
        pdData_abs_sqrt[i] = abs(pdData[i]);
    }
    double ave3;
    AverageCal(pdData_abs_sqrt, number, &ave3);
    double valid;
    ValidCal(pdData, number, &valid);
    *pdDataOut = valid / ave3;
    return 0;
}


//*******************************************************************************
//* 模块名称：SquarerootAmCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求方根幅值
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::SquarerootAmCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int i;
    double* pdData_abs_sqrt = new double[number];
    for (i = 0; i < number; i++)
    {
        pdData_abs_sqrt[i] = sqrt(abs(pdData[i]));
    }
    double ave3;
    AverageCal(pdData_abs_sqrt, number, &ave3);
    ave3 = ave3 * ave3;
    *pdDataOut = ave3;
    return 0;
}

//*******************************************************************************
//* 模块名称：SkewnessCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求偏度
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::SkewnessCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double ave;
    AverageCal(pdData, number, &ave);
    double std;
    StdCal2(pdData, number, &std);
    double sum = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        sum = sum + pow(((pdData[i] - ave) / std), 3);
    }
    *pdDataOut = sum / number;
    return 0;
}

//*******************************************************************************
//* 模块名称：KurtosisCal(T* pdData,int number, T* pdDataOut)
//* 模块功能：求峭度
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*           number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：2023-11-22
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::KurtosisCal(T* pdData, int number, T* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    double ave;
    AverageCal(pdData, number, &ave);
    double sum = 0;
    double sum2 = 0;
    int i;
    for (i = 0; i < number; i++)
    {
        sum = sum + pow((pdData[i] - ave), 4);
        sum2 = sum2 + pow((pdData[i] - ave), 2);
    }
    *pdDataOut = (sum / number) / pow((sum2 / number), 2);
    return 0;
}

template<class T>
int AMCUtilityAlgDataAnalysis::time_parameter_calculata(T* pdData, int number, vector<vector<double>>& pdDataout) 
{
    if ((number < 1) || (pdData == 0))
    {
        return -1;
    }
    //平均值
    double sum = 0;        //求和
    double average = 0;    //平均值
    double abs_sum = 0;    //求绝对值的和
    double max = pdData[0];//最大值
    double min = pdData[0];//最小值
    double mean_square = 0;//均方值
    double* pdData_abs_sqrt = new double[number];//方根幅值相关变量
    double mean_square_sqrt = 0;//均方根
    double square_sqrt_abs;//根幅值
    double var = 0;//方差
    double var2 = 0;//方差2，方差2与1的区别在分母，方差2分母为N，方差1分母为N-1
    double std = 0;//标准差
    double std2 = 0;//标准差2，标准差2与1的区别在分母，标准差2分母为N，标准差1分母为N-1
    double skeness = 0;//偏度相关变量
    double kurtosis = 0;//峭度相关变量
    vector<double>peak;//峰值
    double MeanSquare = 0;
    int i;
    int j = 0;
    for (i = 0; i < number; i++)
    {
        sum = sum + pdData[i];
        abs_sum = abs_sum + abs(pdData[i]);
        MeanSquare += pdData[i] * pdData[i];
        if (pdData[i] > max) {
            max = pdData[i];
        }
        if (pdData[i] < min) {
            min = pdData[i];
        }
        if ((pdData[i] > pdData[i - 1]) && (pdData[i] > pdData[i + 1]))
        {
            j++;
            peak.push_back(pdData[i]);
        }
        pdData_abs_sqrt[i] = sqrt(abs(pdData[i]));
    }
    //方差计算的循环
    average = sum / number;
    double varcal = 0;
    for (i = 0; i < number; i++)
    {
        varcal = varcal + (pdData[i] - average) * (pdData[i] - average);
    }
    var = varcal / (number - 1);
    var2 = varcal / (number);
    //平均值
    vector<double>average_vector;
    average_vector.push_back(average);
    pdDataout.push_back((average_vector));
    //最大值
    vector<double>max_vector;
    max_vector.push_back(max);
    pdDataout.push_back(max_vector);
    //最小值
    vector<double>min_vector;
    min_vector.push_back(min);
    pdDataout.push_back(min_vector);
    //均方值
    mean_square = MeanSquare / number;
    vector<double>mean_square_vector;
    mean_square_vector.push_back(mean_square);
    pdDataout.push_back(mean_square_vector);
    //均方根值(物理上也多被称为有效值)
    mean_square_sqrt = sqrt(mean_square);
    vector<double>mean_square_sqrt_vector;
    mean_square_sqrt_vector.push_back(mean_square_sqrt);
    pdDataout.push_back(mean_square_sqrt_vector);
    //方根幅值
    AverageCal(pdData_abs_sqrt, number, &square_sqrt_abs);
    vector<double>square_sqrt_abs_vector;
    square_sqrt_abs_vector.push_back(square_sqrt_abs * square_sqrt_abs);
    pdDataout.push_back(square_sqrt_abs_vector);
    //方差
    vector<double> varcal_vector;
    varcal_vector.push_back(var);
    pdDataout.push_back(varcal_vector);
    //标准差
    std = sqrt(var);
    std2 = sqrt(var2);
    vector<double>std_vector;
    std_vector.push_back(std);
    pdDataout.push_back(std_vector);
    //峰峰值
    vector<double>peak_peak_vector;
    peak_peak_vector.push_back(max - min);
    pdDataout.push_back(peak_peak_vector);
    //峰值
    pdDataout.push_back(peak);
    //峰值因子
    vector<double>peak_factor_vector;
    int peaknum = peak.size();
    for (int i = 0; i < peaknum; i++)
    {
        peak_factor_vector.push_back(peak[i] / mean_square_sqrt_vector[0]);
    }
    pdDataout.push_back(peak_factor_vector);
    //脉冲因子
    vector<double>pulse_factor_vector;
    for (int i = 0; i < peaknum; i++)
    {
        pulse_factor_vector.push_back(peak[i] / (abs_sum / number));
    }
    pdDataout.push_back(pulse_factor_vector);
    //裕度因子
    vector<double>margin_factor_vector;
    for (int i = 0; i < peaknum; i++)
    {
        margin_factor_vector.push_back(peak[i] / (square_sqrt_abs * square_sqrt_abs));
    }
    pdDataout.push_back(margin_factor_vector);
    //波形因子
    vector<double>form_factor_vector;
    form_factor_vector.push_back(mean_square_sqrt / (abs_sum / number));
    pdDataout.push_back(form_factor_vector);
    //偏度
    for (int i = 0; i < number; i++)
    {
        skeness = skeness + pow((pdData[i] - average) / std2, 3);
    }
    vector<double>skewness_factor;
    skewness_factor.push_back(skeness / number);
    pdDataout.push_back(skewness_factor);
    //峭度
    for (int i = 0; i < number; i++)
    {
        kurtosis = kurtosis + pow((pdData[i] - average) / std2, 4);
    }
    vector<double>kurtosis_factor;
    kurtosis_factor.push_back(kurtosis / number);
    pdDataout.push_back(kurtosis_factor);
    return 0;
}

//*******************************************************************************
//* 模块名称：FFTCal(T* pdData, double fs, int number, int fftlen, vector<vector<double>>* pdDataOut)
//* 模块功能：求FFT
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*            number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//*            fftlen            (in) FFT运算长度
//*            fs                (in) 采样率
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************
template<class T>
int AMCUtilityAlgDataAnalysis::FFTCal(T* pdData, double fs, int number, 
	int fftlen, vector<vector<double>>* pdDataOut)
{
    //0~800Hz对应的点数截取

    int flen = 800 / fs * fftlen;

    if ((number < 1) || (pdData == 0))
    {
        return -1;
    }
    double sum = 0;
    vector<double> dataout;
    vector<vector<double>> result;
    arma::vec pdData1 = arma::vec(pdData, number);
    cx_mat Y = (fft(pdData1, fftlen));
    arma::vec abs_Y = arma::abs(Y);
    //abs_Y.save("FFT.csv", arma::raw_ascii);//FFT结果存储
    //频率值
    for (int j = 0; j < flen; j++)
    {
        double double_j = double(j);
        dataout.push_back(double_j / fftlen * fs);
    }
    //不同频率下的幅度值
    for (int i = 0; i < flen; i++)
    {
        dataout.push_back(abs_Y[i]);
    }
    for (size_t i = 0; i < dataout.size(); i += flen)
    {
        vector<double>temp(dataout.begin() + i, dataout.begin() + i + flen);
        result.push_back(temp);                                                  // 将提取的元素放入新的vector中，并添加到结果vector中
    }
    *pdDataOut = result;

    return 0;
}

//*******************************************************************************
//* 模块名称：EnvelopeCal(T* pdData, double fs, int number, int fftlen, vector<vector<double>>* pdDataOut)
//* 模块功能：包络分析
//* 参数说明：*pdData	    	 (in) 待运算的数组.
//*            number	    	 (in) 数组长度.
//*           *pdDataOut    	 (in) 运算完的数组.
//*            fftlen            (in) FFT运算长度
//*            fs                (in) 采样率
//* 返回值  ：0:计算成功 -1:计算失败
//* 建立时间：
//* 创建人员：
//* 修改日期：
//* 修改人员：
//*******************************************************************************

template<class T>
int AMCUtilityAlgDataAnalysis::EnvelopeCal(T* pdData, double fs, int number, int fftlen, vector<vector<double>>* pdDataOut)
{
    if ((number < 1) || (pdData == 0) || (pdDataOut == 0))
    {
        return -1;
    }
    int flen = 800 / fs * fftlen;
    double sum = 0;
    vector<double> dataout;
    vector<vector<double>> result;
    arma::vec pdData1 = arma::vec(pdData, number);
    cx_mat Y = fft(pdData1, fftlen);
    for (int i = 0; i < fftlen / 2; i++)
    {
        Y[i + fftlen / 2] = 0;                                                        //Hilbert后FFT结果
    }
    //Y.save("Y.csv", arma::raw_ascii);
    cx_mat Hilbert = ifft(Y, fftlen);                                             //Hilbert变换
    arma::vec Hilbert_abs = abs(Hilbert);                                         //求取信号包络
    cx_mat Hilbert_abs_FFT = fft(Hilbert_abs, fftlen);
    arma::vec Hilbert_abs_FFT_abs = abs(Hilbert_abs_FFT);                         //包络FFT取ABS
    //Hilbert_abs_FFT_abs.save("Hilbert_abs_FFT_abs.csv", arma::raw_ascii);       //包络FFTabs结果存储             

    double norm = 0;                                              //计算二范数，用来后续归一化
    for (int i = 0; i < fftlen; i++)
    {
        norm = norm + Hilbert_abs_FFT_abs[i] * Hilbert_abs_FFT_abs[i];
    }
    norm = sqrt(norm);
    arma::vec Hilbert_abs_FFT_norma = Hilbert_abs_FFT_abs / norm;

    //Hilbert_abs_FFT_norma.save("Envelopcal.csv", arma::raw_ascii);//包络FFTabs归一化结果存储    

    for (int j = 0; j < flen; j++)
    {
        double double_j = double(j);
        dataout.push_back(double_j / fftlen * fs);
    }

    for (int i = 0; i < flen; i++)
    {
        dataout.push_back(Hilbert_abs_FFT_abs[i]);
    }
    for (size_t i = 0; i < dataout.size(); i += flen)
    {
        vector<double>temp(dataout.begin() + i, dataout.begin() + i + flen);
        result.push_back(temp);                                                  // 将提取的元素放入新的vector中，并添加到结果vector中
    }
    *pdDataOut = result;
    return 0;
}

#endif // AMCUTILITYALGDATAANALYSIS_H
